import {
  app,
  BrowserWindow,
  ipcMain,
  dialog,
  Menu,
  PrintToPDFOptions,
} from "electron";
// import { createRequire } from 'node:module'
import { fileURLToPath } from "node:url";
import path from "node:path";
import fs from "node:fs";
import { promisify } from "node:util";

const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
const mkdir = promisify(fs.mkdir);
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
const unlink = promisify(fs.unlink);
const rmdir = promisify(fs.rmdir);

// const require = createRequire(import.meta.url)
const __dirname = path.dirname(fileURLToPath(import.meta.url));

// The built directory structure
//
// ├─┬─┬ dist
// │ │ └── index.html
// │ │
// │ ├─┬ dist-electron
// │ │ ├── main.js
// │ │ └── preload.mjs
// │
process.env.APP_ROOT = path.join(__dirname, "..");

// 🚧 Use ['ENV_NAME'] avoid vite:define plugin - Vite@2.x
export const VITE_DEV_SERVER_URL = process.env["VITE_DEV_SERVER_URL"];
export const MAIN_DIST = path.join(process.env.APP_ROOT, "dist-electron");
export const RENDERER_DIST = path.join(process.env.APP_ROOT, "dist");

process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL
  ? path.join(process.env.APP_ROOT, "public")
  : RENDERER_DIST;

let win: BrowserWindow | null;

function createWindow() {
  win = new BrowserWindow({
    icon: path.join(process.env.VITE_PUBLIC, "electron-vite.svg"),
    webPreferences: {
      preload: path.join(__dirname, "preload.mjs"),
      nodeIntegration: true,
      contextIsolation: true,
    },
  });

  // Test active push message to Renderer-process.
  win.webContents.on("did-finish-load", () => {
    win?.webContents.send("main-process-message", new Date().toLocaleString());
  });

  if (VITE_DEV_SERVER_URL) {
    win.loadURL(VITE_DEV_SERVER_URL);
  } else {
    // win.loadFile('dist/index.html')
    win.loadFile(path.join(RENDERER_DIST, "index.html"));
  }
}

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
    win = null;
  }
});

app.on("activate", () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

// 文件系统操作IPC处理程序
ipcMain.handle("fs:readFile", async (_event, filePath) => {
  try {
    const content = await readFile(filePath, "utf-8");
    return { success: true, content };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
});

ipcMain.handle("fs:writeFile", async (_event, filePath, content) => {
  try {
    await writeFile(filePath, content, "utf-8");
    return { success: true };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
});

ipcMain.handle("fs:createDirectory", async (_event, dirPath) => {
  try {
    await mkdir(dirPath, { recursive: true });
    return { success: true };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
});

ipcMain.handle("fs:readDirectory", async (_event, dirPath) => {
  try {
    const items = await readdir(dirPath, { withFileTypes: true });
    const files = await Promise.all(
      items.map(async (item) => {
        const fullPath = path.join(dirPath, item.name);
        const stats = await stat(fullPath);
        return {
          name: item.name,
          path: fullPath,
          isDirectory: item.isDirectory(),
          isFile: item.isFile(),
          size: stats.size,
          modifiedTime: stats.mtime,
        };
      })
    );
    return { success: true, files };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
});

ipcMain.handle("dialog:openFile", async (_event) => {
  try {
    if (!win) {
      return { canceled: true, error: "No active window" };
    }
    const result = await dialog.showOpenDialog(win, {
      properties: ["openFile"],
      filters: [
        { name: "Markdown Files", extensions: ["md", "markdown"] },
        { name: "Text Files", extensions: ["txt"] },
        { name: "All Files", extensions: ["*"] },
      ],
    });
    return result;
  } catch (error: any) {
    return { canceled: true, error: error.message };
  }
});

ipcMain.handle("dialog:saveFile", async (_event, defaultPath) => {
  try {
    if (!win) {
      return { canceled: true, error: "No active window" };
    }
    const result = await dialog.showSaveDialog(win, {
      defaultPath,
      filters: [
        { name: "Markdown Files", extensions: ["md"] },
        { name: "Text Files", extensions: ["txt"] },
      ],
    });
    return result;
  } catch (error: any) {
    return { canceled: true, error: error.message };
  }
});

ipcMain.handle("dialog:selectDirectory", async (_event) => {
  try {
    if (!win) {
      return { canceled: true, error: "No active window" };
    }
    const result = await dialog.showOpenDialog(win, {
      properties: ["openDirectory"],
    });
    return result;
  } catch (error: any) {
    return { canceled: true, error: error.message };
  }
});

ipcMain.handle("fs:deleteFile", async (_event, filePath) => {
  try {
    await unlink(filePath);
    return { success: true };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
});

ipcMain.handle("fs:deleteDirectory", async (_event, dirPath) => {
  try {
    await rmdir(dirPath);
    return { success: true };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
});

ipcMain.handle("fs:rename", async (_event, oldPath, newPath) => {
  try {
    await promisify(fs.rename)(oldPath, newPath);
    return { success: true };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
});

// 新建文件IPC处理程序
ipcMain.handle("file:new", async (_event) => {
  try {
    if (!win) {
      return { canceled: true, error: "No active window" };
    }
    const result = await dialog.showSaveDialog(win, {
      title: "新建文件",
      filters: [
        { name: "Markdown Files", extensions: ["md"] },
        { name: "Text Files", extensions: ["txt"] },
      ],
    });

    if (!result.canceled && result.filePath) {
      await writeFile(result.filePath, "", "utf-8");
      return { success: true, filePath: result.filePath };
    }
    return { success: false, canceled: true };
  } catch (error: any) {
    return { success: false, error: error.message };
  }
});

// 导出pdf
ipcMain.handle(
  "file:export-pdf",
  async (_event, defaultPath: string, options: PrintToPDFOptions) => {
    if (!win) return { success: false };

    try {
      const pdf = await win.webContents.printToPDF(options);

      const result = await dialog.showSaveDialog(win, {
        defaultPath: defaultPath || "exports.pdf",
        filters: [{ name: "PDF Files", extensions: ["pdf"] }],
      });

      if (!result.canceled && result.filePath) {
        await writeFile(result.filePath, pdf);
        return { success: true, filePath: result.filePath };
      }

      return { success: false, canceled: true };
    } catch (error: any) {
      return { success: false, error: error.message };
    }
  }
);

// 创建菜单
function createMenu() {
  const template: Electron.MenuItemConstructorOptions[] = [
    {
      label: "File",
      submenu: [
        {
          label: "New File",
          accelerator: "CmdOrCtrl+N",
          click: async () => {
            if (win) {
              try {
                const result = await dialog.showSaveDialog(win, {
                  title: "新建文件",
                  filters: [
                    { name: "Markdown Files", extensions: ["md"] },
                    { name: "Text Files", extensions: ["txt"] },
                  ],
                });

                if (!result.canceled && result.filePath) {
                  await writeFile(result.filePath, "", "utf-8");
                  win.webContents.send("file:created", result.filePath);
                  win.webContents.send("file:new-created", result.filePath);
                }
              } catch (error: any) {
                console.error("Error creating new file:", error);
              }
            }
          },
        },
        { type: "separator" },
        {
          label: "Open File",
          accelerator: "CmdOrCtrl+O",
          click: async () => {
            if (win) {
              const result = await dialog.showOpenDialog(win, {
                properties: ["openFile"],
                filters: [
                  { name: "Markdown Files", extensions: ["md", "markdown"] },
                  { name: "Text Files", extensions: ["txt"] },
                  { name: "All Files", extensions: ["*"] },
                ],
              });
              if (!result.canceled && result.filePaths.length > 0) {
                win.webContents.send("file:opened", result.filePaths[0]);
              }
            }
          },
        },
        {
          label: "Save",
          accelerator: "CmdOrCtrl+S",
          click: async () => {
            if (win) {
              win.webContents.send("file:save");
            }
          },
        },
        {
          label: "Save As",
          accelerator: "CmdOrCtrl+Shift+S",
          click: async () => {
            if (win) {
              win.webContents.send("file:save-as");
            }
          },
        },
        { type: "separator" },
        {
          label: "Export PDF",
          accelerator: "CmdOrCtrl+P",
          click: async () => {
            if (win) {
              win.webContents.send("file:export-pdf");
            }
          },
        },
        { type: "separator" },
        {
          role: "quit",
          accelerator: "CmdOrCtrl+Q",
        },
      ],
    },
    {
      label: "Edit",
      submenu: [
        { role: "undo", accelerator: "CmdOrCtrl+Z" },
        { role: "redo", accelerator: "CmdOrCtrl+Shift+Z" },
        { type: "separator" },
        { role: "cut", accelerator: "CmdOrCtrl+X" },
        { role: "copy", accelerator: "CmdOrCtrl+C" },
        { role: "paste", accelerator: "CmdOrCtrl+V" },
        { role: "selectAll", accelerator: "CmdOrCtrl+A" },
      ],
    },
    {
      label: "View",
      submenu: [{ role: "toggleDevTools", accelerator: "CmdOrCtrl+I" }],
    },
  ];

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
}

app.whenReady().then(() => {
  createWindow();
  createMenu();
});